<?php

namespace PhpYes\Modules\Cmd;


final class ArgumentObject
{
    const ArgTypePosition = 0;
    const ArgTypeShort = 1;
    const ArgTypeLong = 2;

    /** @var bool */
    private $isParsed;

    /** @var string */
    private $argRaw;
    /** @var CmdArgumentDefinitions */
    private $cmdArgumentDefinitions;
    /**
     * refer self::ArgTypeXX
     * @var int
     */
    private $argType;
    /** @var string */
    private $arg;
    /** @var string */
    private $value;
    /** @var ArgumentDefinition */
    private $argumentDefinition;

    /**
     * ArgumentObject constructor.
     * @param string $argRaw
     * @param CmdArgumentDefinitions $cmdArgumentDefinitions
     */
    public function __construct($argRaw, CmdArgumentDefinitions $cmdArgumentDefinitions)
    {
        $this->isParsed = false;
        $this->argRaw = $argRaw;
        $this->cmdArgumentDefinitions = $cmdArgumentDefinitions;
        $this->argType = self::ArgTypePosition;
    }

    /**
     * @return string
     */
    public function getArgRaw()
    {
        return $this->argRaw;
    }

    /**
     * @return CmdArgumentDefinitions
     */
    public function getCmdArgumentDefinitions()
    {
        return $this->cmdArgumentDefinitions;
    }

    /**
     * @return int
     */
    public function getArgType()
    {
        if (!$this->isParsed) {
            $this->parse();
        }

        return $this->argType;
    }

    /**
     * @return string
     */
    public function getArg()
    {
        if (!$this->isParsed) {
            $this->parse();
        }

        return $this->arg;
    }

    /**
     * @return string
     */
    public function getValue()
    {
        if (!$this->isParsed) {
            $this->parse();
        }

        return $this->value;
    }

    /**
     * @return ArgumentDefinition
     */
    public function getArgumentDefinition()
    {
        if (!$this->isParsed) {
            $this->parse();
        }

        return $this->argumentDefinition;
    }

    private function parse()
    {
        if ($this->isParsed) {
            return;
        }
        $this->isParsed = true;

        $shortMapping = $this->cmdArgumentDefinitions->getShortMapping();
        if (isset($shortMapping[$this->argRaw])) {
            $this->argType = self::ArgTypeShort;
            $this->arg = $this->argRaw;
            $this->value = null;
            $this->argumentDefinition = $shortMapping[$this->argRaw];

            return;
        }

        $longMapping = $this->cmdArgumentDefinitions->getLongMapping();
        $arg = $this->argRaw;
        $val = null;
        if (isset($longMapping[$arg])) {
            $this->argType = self::ArgTypeLong;
            $this->arg = $arg;
            $this->value = $val;
            $this->argumentDefinition = $longMapping[$arg];

            return;
        }

        $pos = strpos($this->argRaw, '=');
        if ($pos === false) {
            return;
        }
        $arg = substr($this->argRaw, 0, $pos);
        $val = substr($this->argRaw, $pos + 1);
        if (empty($val)) {
            $val = '';
        }
        if (isset($longMapping[$arg])) {
            $this->argType = self::ArgTypeLong;
            $this->arg = $arg;
            $this->value = $val;
            $this->argumentDefinition = $longMapping[$arg];

            return;
        }
    }

}